package com.freewater.springboot.demo.ioc.qualifier;

import com.freewater.springboot.demo.PackageUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;

/**
 * Autowired + Qualifier 组合后，注入逻辑：
 * 1、Autowired是按照类型查询；
 * 2、以前的错误理解：Qualifier的value值等同于bean的id或者name值，用Qualifier到达使用bean名称注入的目的（这是错误的，
 * Qualifier的value值是一个筛选器，在xml配置中，一个bean可以配置一个qualifier的子元素标定这个bean的qualifier，且不同的
 * bean可以配置相同的qualifier值，见applicationContext.xml。所以如果使用Qualifier注解过滤后可能得到的是多个
 * 使用相同qualifier的bean）。
 * 3、如果Qualifier的value，过滤后仍然有多个bean，那么Spring进一步根据参数名或者字段名过滤（由于bean默认使用name作为qualifier，
 * 这给了我们一个错觉，Qualifier配合Autowired就是用来使用bean名称注入的）。
 */
@Slf4j
public class Main {

    public static void main(String[] args) {
        GenericApplicationContext applicationContext = new GenericApplicationContext();
        final String xmlPath = PackageUtils.getDefaultAppContextXmlPath(Main.class);
        new XmlBeanDefinitionReader(applicationContext).loadBeanDefinitions(xmlPath);
        applicationContext.refresh();
        log.info("使用ApplicationContext：{}", xmlPath);
        applicationContext.start();
        applicationContext.registerShutdownHook(); // 注册jvm关闭回调，jvm关闭时一并关闭spring容器
        final MovieRecommender movieRecommender1 = (MovieRecommender) applicationContext.getBean("movieRecommender1");
        System.out.println(movieRecommender1.getMovieCatalogsMap1().keySet()); // [movieCatalog1, movieCatalog2]
        System.out.println(movieRecommender1.getMovieCatalogsMap2().keySet()); // [movieCatalog3, movieCatalog4]
        System.out.println(movieRecommender1.getMovieCatalog1().getBeanName()); // movieCatalog1
        System.out.println(movieRecommender1.getMovieCatalog3().getBeanName()); // movieCatalog3
        System.out.println(movieRecommender1.getMovieRecommender().getBeanName());
        final MovieRecommender movieRecommender2 = (MovieRecommender) applicationContext.getBean("movieRecommender2");
        System.out.println(movieRecommender2.getMovieRecommender().getBeanName());
    }
}
